package com.xinyu.notification;

import com.xinyu.config.NotificationProperties;
import com.xinyu.domain.Daily;
import com.xinyu.domain.Task;
import com.xinyu.event.StatusChangeEvent;
import com.xinyu.utils.StatusLabelUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * Helper component to publish task status/assignee change notifications from different entry points.
 */
@Component
public class TaskStatusChangePublisher {

    private final ApplicationEventPublisher eventPublisher;
    private final NotificationProperties notificationProperties;

    public TaskStatusChangePublisher(ApplicationEventPublisher eventPublisher,
                                     NotificationProperties notificationProperties) {
        this.eventPublisher = eventPublisher;
        this.notificationProperties = notificationProperties;
    }

    public void publish(Task updatedTask,
                        Task previousTask,
                        Daily relatedDaily,
                        Integer operatorId,
                        String reason) {
        if (updatedTask == null || previousTask == null) {
            return;
        }
        boolean stateChanged = !Objects.equals(previousTask.getState(), updatedTask.getState());
        boolean responsibleChanged = !Objects.equals(previousTask.getResponsibleUserId(), updatedTask.getResponsibleUserId());
        if (!stateChanged && !responsibleChanged) {
            return;
        }
        Set<Integer> recipients = new LinkedHashSet<>();
        if (previousTask.getPublishUserId() != null) {
            recipients.add(previousTask.getPublishUserId());
        }
        if (updatedTask.getResponsibleUserId() != null) {
            recipients.add(updatedTask.getResponsibleUserId());
        } else if (previousTask.getResponsibleUserId() != null) {
            recipients.add(previousTask.getResponsibleUserId());
        }
        if (responsibleChanged && previousTask.getResponsibleUserId() != null) {
            recipients.add(previousTask.getResponsibleUserId());
        }
        if (relatedDaily != null && relatedDaily.getLogUserId() != null) {
            recipients.add(relatedDaily.getLogUserId());
        }
        List<Integer> recipientList = new ArrayList<>(recipients);
        if (recipientList.isEmpty()) {
            return;
        }
        StatusChangeEvent event = new StatusChangeEvent(
                StatusChangeEvent.EntityType.TASK,
                updatedTask.getId(),
                StringUtils.defaultIfBlank(updatedTask.getTitle(), previousTask.getTitle()),
                previousTask.getState(),
                updatedTask.getState(),
                StatusLabelUtils.taskStateLabel(updatedTask.getState()),
                reason,
                operatorId,
                recipientList,
                notificationProperties.buildTaskDetailUrl(updatedTask.getId()),
                stateChanged,
                responsibleChanged,
                previousTask.getResponsibleUserId(),
                updatedTask.getResponsibleUserId()
        );
        eventPublisher.publishEvent(event);
    }
}
